package 多线程;

/*使用Atomic

Java的java.util.concurrent包除了提供底层锁、并发集合外，还提供了一组原子操作的封装类，它们位于java.util.concurrent.atomic包。

我们以AtomicInteger为例，它提供的主要操作有：

-增加值并返回新值：int addAndGet(int delta)
-加1后返回新值：int incrementAndGet()
-获取当前值：int get()
-用CAS方式设置：int compareAndSet(int expect, int update)

Atomic类是通过无锁（lock-free）的方式实现的线程安全（thread-safe）访问。它的主要原理是利用了CAS：Compare and Set。

如果我们自己通过CAS编写incrementAndGet()，它大概长这样：

public int incrementAndGet(AtomicInteger var) {
    int prev, next;
    do {
        prev = var.get();
        next = prev + 1;
    } while ( ! var.compareAndSet(prev, next));
    return next;
}
CAS是指，在这个操作中，如果AtomicInteger的当前值是prev，那么就更新为next，返回true。如果AtomicInteger的当前
值不是prev，就什么也不干，返回false。通过CAS操作并配合do ... while循环，即使其他线程修改了AtomicInteger的值，
最终的结果也是正确的。

我们利用AtomicLong可以编写一个多线程安全的全局唯一ID生成器：

class IdGenerator {
    AtomicLong var = new AtomicLong(0);

    public long getNextId() {
        return var.incrementAndGet();
    }
}
通常情况下，我们并不需要直接用do ... while循环调用compareAndSet实现复杂的并发操作，而是用incrementAndGet()这样的封
装好的方法，因此，使用起来非常简单。

在高度竞争的情况下，还可以使用Java 8提供的LongAdder和LongAccumulator。
*/

/*一个标准的CAS包含三个操作：

1.将要操作的内存地址M。
2.现有的变量A。
3.新的需要存储的变量B。

CAS将会先比较A和M中存储的值是否一致，一致则表示其他线程未对该变量进行修改，则将其替换为B。 否则不做任何操作。

每一个CAS操作过程都包含三个参数：一个内存地址V，一个期望的值A和一个新值B，操作的时候如果这个地址上存放的值等于这个期望的值A，则将地址上的值赋为
新值B，否则不做任何操作。CAS的基本思路就是，如果这个地址上的值和期望的值相等，则给其赋予新值，否则不做任何事儿.

使用CAS可以不用阻塞其他的线程，但是我们需要自己处理好当更新失败的情况下的业务逻辑处理情况。

Java提供了很多Atomic类，最常用的包括AtomicInteger, AtomicLong, AtomicBoolean, 和 AtomicReference.

其中的主要方法：

1.get() – 直接中主内存中读取变量的值，类似于volatile变量。
2.set() – 将变量写回主内存。类似于volatile变量。
3.lazySet() – 延迟写回主内存。一种常用的情景是将引用重置为null的情况。
4.compareAndSet() – 执行CAS操作，成功返回true，失败返回false。
5.weakCompareAndSet() – 比较弱的CAS操作，不同的是它不执行happens-before操作，从而不保证能够读取到其他变量最新的值。
我们看下怎么用：

public class AtomicCounter {

    private final AtomicInteger counter = new AtomicInteger(0);

    public int getValue() {
        return counter.get();
    }
    public void increment() {
        while(true) {
            int existingValue = getValue();
            int newValue = existingValue + 1;
            if(counter.compareAndSet(existingValue, newValue)) {//比较
                return;
            }
        }
    }
}
*/

//Atomic简介
//​  Atomic包是java.util.concurrent下的另一个专门为线程安全设计的Java包，包含多个原子操作类这个包里面提供了一组原子变量类。
//
//​   其基本的特性就是在多线程环境下，当有多个线程同时执行这些类的实例包含的方法时，具有排他性，即当某个线程进入方法，执行其中的指令时，不会被
//其他线程打断，而别的线程就像自旋锁一样，一直等到该方法执行完成，才由JVM从等待队列中选择一个另一个线程进入，这只是一种逻辑上的理解。实际上是
//借助硬件的相关指令来实现的，不会阻塞线程(或者说只是在硬件级别上阻塞了)。可以对基本数据、数组中的基本数据、对类中的基本数据进行操作。原子变量
//类相当于一种泛化的volatile变量，能够支持原子的和有条件的读-改-写操作。
//
//传统锁的问题
//我们先来看一个例子：计数器（Counter），采用Java里比较方便的锁机制synchronized关键字，初步的代码如下：

//class Counter {
//	private int value;
//	public synchronized int getValue() {
//		return value;
//	}
//	public synchronized int increment() {
//		return ++value;
//	}
//	public synchronized int decrement() {
//		return --value;
//	}
//}
//   其实像这样的锁机制，满足基本的需求是没有问题的了，但是有的时候我们的需求并非这么简单，我们需要更有效，更加灵活的机制，synchronized关键字是基于
//阻塞的锁机制，也就是说当一个线程拥有锁的时候，访问同一资源的其它线程需要等待，直到该线程释放锁，这里会有些问题：首先，如果被阻塞的线程优先级很高很
//重要怎么办？其次，如果获得锁的线程一直不释放锁怎么办？（这种情况是非常糟糕的）。还有一种情况，如果有大量的线程来竞争资源，那CPU将会花费大量的时间
//和资源来处理这些竞争（事实上CPU的主要工作并非这些），同时，还有可能出现一些例如死锁之类的情况，最后，其实锁机制是一种比较粗糙，粒度比较大的机制，
//相对于像计数器这样的需求有点儿过于笨重，因此，对于这种需求我们期待一种更合适、更高效的线程安全机制，于是CAS诞生了。
//
//传送门：CAS
//Atomic
//java.util.concurrent.atomic中的类可以分成4组：
//
//1.标量类（Scalar）：AtomicBoolean，AtomicInteger，AtomicLong，AtomicReference
//2.数组类：AtomicIntegerArray，AtomicLongArray，AtomicReferenceArray
//3.更新器类：AtomicLongFieldUpdater，AtomicIntegerFieldUpdater，AtomicReferenceFieldUpdater
//  可用于使用反射以原子方式更新类的易失性字段。要获得对这些类的对象的引用，您需要使用他们的工厂方法newUpdater()。
//4.复合变量类：AtomicMarkableReference，AtomicStampedReference

//1.基础数据型
//第一组AtomicBoolean，AtomicInteger，AtomicLong，AtomicReference这四种基本类型用来处理布尔，整数，长整数，对象四种数据，其内部实现不
//是简单的使用synchronized，而是一个更为高效的方式CAS (compare and swap) + volatile和native方法，从而避免了synchronized的高开销，执
//行效率大为提升。我们来看个例子，与我们平时i++所对应的原子操作为：getAndIncrement()
////
/*
* 使用原子变量类定义一个计数器
* 该计数器在整个程序中都能使用，并且在所有的地方都可以使用这个计数器，
* 这个计数器可以设计为单例
* */
/*
import java.util.concurrent.atomic.AtomicLong;
import java.util.Random;

class Indicator {
	// 构造方法私有化   构造函数
	private Indicator() {
	}

	// 定义一个私有的本类静态的对象
	private static final Indicator INSTANCE = new Indicator();

	// 提供一个公共静态方法返回唯一实例
	public static Indicator getInstance() {
		return INSTANCE;
	}

	// 使用原子变量类保存请求总数，成功数，失败数,初始值为0
	private final AtomicLong requestCount = new AtomicLong(0);
	private final AtomicLong successCount = new AtomicLong(0);
	private final AtomicLong failureCount = new AtomicLong(0);

	// 有新的请求
	public void requestProcessReceive() {
		requestCount.incrementAndGet();
	}

	// 处理成功
	public void requestProcessSuccess() {
		successCount.incrementAndGet();
	}

	// 处理失败
	public void requestProcessFailur() {
		failureCount.incrementAndGet();
	}

	// 查看总数，
	public long getRequestCount() {
		return requestCount.get();
	}

	// 查看成功数
	public long getSuccessCount() {
		return successCount.get();
	}

	// 查看失败数
	public long getFailurCount() {
		return failureCount.get();
	}
}

public class 使用Atomic {
	public static void main(String[] args) {
		// 通过线程模拟请求
		for (int i = 0; i < 10000; i++) {
			new Thread(()->{
				// 每个线程就是一个请求，请求总数要+1
				Indicator.getInstance().requestProcessReceive();
				int num = new Random().nextInt();
				if (num % 2 == 0) { // 处理成功
					Indicator.getInstance().requestProcessSuccess();
				} else { // 处理失败
					Indicator.getInstance().requestProcessFailur();
				}
			}).start();
		}

		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("总 数: " + Indicator.getInstance().getRequestCount());// 总数
		System.out.println("成功数: " + Indicator.getInstance().getSuccessCount());// 成功数
		System.out.println("失败数: " + Indicator.getInstance().getFailurCount());// 失败数

	}
}*/
//常用方法
//-构造函数（两个构造函数）
//  --默认的构造函数：初始化的数据分别是false，0，0，null
//  --带参构造函数：参数为初始化的数据
//-set()和get()方法：可以原子地设定和获取atomic的数据。类似于volatile，保证数据会在主存中设置或读取
//
//-void set()和void lazySet()：set设置为给定值，直接修改原始值；lazySet延时设置变量值，这个等价于set()方法，但是由于字段是volatile类型
//   的，因此次字段的修改会比普通字段（非volatile字段）有稍微的性能延时（尽管可以忽略），所以如果不是想立即读取设置的新值，允许在“后台”修改值，那么
//   此方法就很有用。
//
//-getAndSet( )方法
//  --原子的将变量设定为新数据，同时返回先前的旧数据
//  --其本质是get( )操作，然后做set( )操作。尽管这2个操作都是atomic，但是他们合并在一起的时候，就不是atomic。在Java的源程序的级别上，如果
//    不依赖synchronized的机制来完成这个工作，是不可能的。只有依靠native方法才可以。
//
//public final int getAndSet(int newValue) {  
//    for (;;) {  
//        int current = get();  
//        if (compareAndSet(current, newValue))  
//            return current;  
//    }  
//}  
//-compareAndSet() 和weakCompareAndSet()方法
//  这两个方法都是conditional modifier方法。接收2个参数，一个是期望数据(expected)，一个是新数据(new)，如果atomic里面的数据和期望数
//  据一致，则将新数据设定给atomic的数据，返回true，表明成功；否则就不设定，并返回false。JSR规范中说：以原子方式读取和有条件地写入变量但不
//  创建任何 happen-before 排序，因此不提供与除 weakCompareAndSet 目标外任何变量以前或后续读取或写入操作有关的任何保证。大意就是说调
//  用weakCompareAndSet时并不能保证不存在happen- before的发生（也就是可能存在指令重排序导致此操作失败）。但是从Java源码来看，其实此
//  方法并没有实现JSR规范的要求，最后效果和 compareAndSet是等效的，都调用了unsafe.compareAndSwapInt()完成操作。
//
//public final boolean compareAndSet(int expect, int update) {  
//    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  
//}  
//public final boolean weakCompareAndSet(int expect, int update) {  
//    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  
//}  
//-对于 AtomicInteger、AtomicLong还提供了一些特别的方法。
//getAndIncrement( )：以原子方式将当前值加 1，相当于线程安全的i++操作。
//incrementAndGet( )：以原子方式将当前值加 1， 相当于线程安全的++i操作。
//getAndDecrement( )：以原子方式将当前值减 1， 相当于线程安全的i--操作。
//decrementAndGet ( )：以原子方式将当前值减 1，相当于线程安全的--i操作。
//addAndGet( )： 以原子方式将给定值与当前值相加， 实际上就是等于线程安全的i =i+delta操作。
//getAndAdd( )：以原子方式将给定值与当前值相加， 相当于线程安全的t=i;i+=delta;return t;操作。
//以实现一些加法，减法原子操作。(注意 --i、++i不是原子操作，其中包含有3个操作步骤：第一步，读取i；第二步，加1或减1；第三步：写回内存)
//
//2.数组型
//AtomicIntegerArray，AtomicLongArray还有AtomicReferenceArray类进一步扩展了原子操作，对这些类型的数组提供了支持。这些类在为其数组元
//素提供 volatile 访问语义方面也引人注目，这对于普通数组来说是不受支持的。
//
//他们内部并不是像AtomicInteger一样维持一个valatile变量，而是全部由native方法实现，如下
//AtomicIntegerArray的实现片断：
//
//private static final Unsafe unsafe = Unsafe.getUnsafe();  
//private static final int base = unsafe.arrayBaseOffset(int[].class);  
//private static final int scale = unsafe.arrayIndexScale(int[].class);  
//private final int[] array;  
//public final int get(int i) {  
//        return unsafe.getIntVolatile(array, rawIndex(i));  
//}  
//public final void set(int i, int newValue) {  
//        unsafe.putIntVolatile(array, rawIndex(i), newValue);  
//}  
//基本使用示例：
//
/*import java.util.concurrent.atomic.AtomicIntegerArray;
//public class AtomicIntegerArrayTest {
public class 使用Atomic {
    public static void main(String[] args) {
        //创建一个指定长度的原子数组
        AtomicIntegerArray atomicIntegerArray=new AtomicIntegerArray(10);
        System.out.println(atomicIntegerArray);//[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        //返回指定位置的元素
        System.out.println(atomicIntegerArray.get(0));//0
        System.out.println(atomicIntegerArray.get(1));//0
        //设置指定位置的元素
        atomicIntegerArray.set(0,10);
        System.out.println(atomicIntegerArray);//[10, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        //先获取指定位置的值在设置
        System.out.println(atomicIntegerArray.getAndSet(1,11));//0
        System.out.println(atomicIntegerArray);//[10, 11, 0, 0, 0, 0, 0, 0, 0, 0]
        //把数组元素加上某个值
        System.out.println(atomicIntegerArray.addAndGet(0,22));//32
        System.out.println(atomicIntegerArray);//[32, 11, 0, 0, 0, 0, 0, 0, 0, 0]
        System.out.println(atomicIntegerArray.getAndAdd(1,33));//11
        System.out.println(atomicIntegerArray);//[32, 44, 0, 0, 0, 0, 0, 0, 0, 0]

        //CAS操作,如果0位置的值是32，就将其值修改为222
        System.out.println(atomicIntegerArray.compareAndSet(0,32,222));//返回ture
        System.out.println(atomicIntegerArray);//[222, 44, 0, 0, 0, 0, 0, 0, 0, 0]
        //先自增在返回
        System.out.println(atomicIntegerArray.incrementAndGet(0));//223
        System.out.println(atomicIntegerArray);//[223, 44, 0, 0, 0, 0, 0, 0, 0, 0]
        //先返回再自减
        System.out.println(atomicIntegerArray.getAndIncrement(1));//44
        System.out.println(atomicIntegerArray);//[223, 45, 0, 0, 0, 0, 0, 0, 0, 0]
        //先自减再返回
        System.out.println(atomicIntegerArray.decrementAndGet(2));//-1
        System.out.println(atomicIntegerArray);//[223, 45, -1, 0, 0, 0, 0, 0, 0, 0]
        //先返回再自减
        System.out.println(atomicIntegerArray.getAndDecrement(3));//0 先get后set
        System.out.println(atomicIntegerArray);//[223, 45, -1, -1, 0, 0, 0, 0, 0, 0]

    }
}
*/

/*import java.util.concurrent.atomic.AtomicIntegerArray;

//public class AtomicIntegerArrayTest01 {
public class 使用Atomic {
	// 定义一个原子数组
	static AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(10);

	public static void main(String[] args) {
		System.out.println(12%atomicIntegerArray.length());
		// 定义线程数组
		Thread[] threads = new Thread[10];
		// 给线程数组赋值
		for (int i = 0; i < threads.length; i++) {
			threads[i] = new addThread();
		}
		// 开启子线程
		for (Thread thread : threads) {
			thread.start();
		}

		// 在主线程中查看自增完后原子数组中各个元素的值，主线程中需要在所有子线程都执行完后查看
		// 把所有的子线程合并到当前主线程中
		for (Thread thread : threads) {
			try {
				thread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(atomicIntegerArray);
	}

	// 定义一个线程类，在线程类中修改原子数组
	static class addThread extends Thread {
		int length=atomicIntegerArray.length();
		@Override
		public void run() {
			// 把数组元素的每个元素自增1000次
			for (int i = 0; i < 1000; i++) {
				for (int j = 0; j < atomicIntegerArray.length(); j++) {
					
					atomicIntegerArray.getAndIncrement(i % length);//atomicIntegerArray.length());
				}
			}
		}
	}
}*/

//输出结果：

////10个线程，每个线程自增1000次
//[10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000]

//3.字段更新器
//AtomicLongFieldUpdater，AtomicIntegerFieldUpdater，AtomicReferenceFieldUpdater基于反射的实用工具，可以对指定类的指
//定 volatile 字段进行原子更新。API非常简单，但是也是有一些约束：
//
//（1）字段必须是volatile类型的(共享变量，任一线程修改，其他线程可立即获得修改后的数值)
//（2）字段的描述类型（修饰符public/protected/default/private）是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段，
//    那么就可以反射进行原子操作。但是对于父类的字段，子类是不能直接操作的，尽管子类可以访问父类的字段。
//（3）只能是实例变量，不能是类变量，也就是说不能加static关键字。
//（4）只能是可修改变量，不能使final变量，因为final的语义就是不可修改。实际上final的语义和volatile是有冲突的，这两个关键字不能同时存在。
//（5）对于AtomicIntegerFieldUpdater 和AtomicLongFieldUpdater 只能修改int/long类型的字段，不能修改其包装类型（Integer/Long）。
//    如果要修改包装类型就需要使用AtomicReferenceFieldUpdater 。
//netty5.0中类ChannelOutboundBuffer统计发送的字节总数，由于使用volatile变量已经不能满足，所以使用AtomicIntegerFieldUpdater来实现的
//
//示例：

//定义一个User实体类
/*import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
class User {
     int id;
     volatile int age;
     volatile int age1;
    public User(int id, int age) {
        this.id = id;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", age=" + age +
                '}';
    }
}
//定义一个线程类，实现字段自增
class AtomicUpdater extends Thread{
    private User user;

    private AtomicIntegerFieldUpdater<User> updater = AtomicIntegerFieldUpdater.newUpdater(User.class,"age");

    public AtomicUpdater(User user) {
        this.user = user;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            //System.out.println(updater.getAndIncrement(user));
            System.out.println(updater.incrementAndGet(user));
        }
    }
}
//测试类
public class 使用Atomic {
    public static void main(String[] args) {
        //初始化User对象
        User user = new User(1, 10);
        //开启10个线程
        for (int i = 0; i < 10; i++) {
            new AtomicUpdater(user).start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(user);
    }
}*/

//输出结果：
//一个线程自增10次，10个线程自增100次
//User{id=1, age=110}

//4.引用型
//原子更新基本类型的AtomicInteger，只能更新一个变量，如果要原子更新多个变量，就需要使用这个原子更新引用类型提供的类。Atomic包提供了以下3个类
//
//(1)AtomicReference
//
/*import java.util.concurrent.atomic.AtomicReference;

//public class AtomicReferenceTest {
public class 使用Atomic {
	static AtomicReference<String> atomicReference = new AtomicReference<>("汉字");

	public static void main(String[] args) {
		// 创建十个线程修改字符串
		for (int i = 0; i < 100; i++) {
			new Thread(() -> {
				if (atomicReference.compareAndSet("汉字", "def")) {
					System.out.println(Thread.currentThread().getName() + "把字符串修改为："+atomicReference.get());
				}
			}).start();
		}
		// 再创建100个线程
		for (int i = 0; i < 100; i++) {
			new Thread(()-> {
				if (atomicReference.compareAndSet("def", "汉字1")) {
					System.out.println(Thread.currentThread().getName() + "把字符串还原为："+atomicReference.get());
				}
			}).start();
		}

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(atomicReference.get());
	}

}*/

//(2)AtomicStampedReference
//由于atomicReference是采用了CAS，所以可能会产生ABA问题。利用版本戳的形式记录了每次改变以后的版本号，这样的话就不会存在ABA问题了。这就
//是AtomicStampedReference的解决方案。
//AtomicStampedReference 原子类的核心源码：
//public class AtomicStampedReference<V> {
//    // Pair对象维护对象的引用和对象标志的版本，通过Pair对象解决“ABA”问题
//    private static class Pair<T> {
//        final T reference;// 对象的引用
//        final int stamp;//  对象标志的版本
//
//        private Pair(T reference, int stamp) {
//            this.reference = reference;
//            this.stamp = stamp;
//        }
//
//        static <T> Pair<T> of(T reference, int stamp) {
//            return new Pair<T>(reference, stamp);
//        }
//    }
//
//    private volatile Pair<V> pair;
//
//    public AtomicStampedReference(V initialRef, int initialStamp) { pair = Pair.of(initialRef, initialStamp); }
//
//    public V getReference() { return pair.reference; }
//
//    public int getStamp() { return pair.stamp; }
//
//    public V get(int[] stampHolder) {
//        Pair<V> pair = this.pair;
//        stampHolder[0] = pair.stamp;
//        return pair.reference;
//    }
//
//    public boolean weakCompareAndSet(V expectedReference,
//                                     V newReference,
//                                     int expectedStamp,
//                                     int newStamp) {
//        return compareAndSet(expectedReference, newReference,
//                expectedStamp, newStamp);
//    }
//
//    /**
//     * @param expectedReference 期待的原始对象
//     * @param newReference      将要更新的对象
//     * @param expectedStamp     期待原始对象的标志版本
//     * @param newStamp          将要更新对象的标志版本
//     */
//    public boolean compareAndSet(V expectedReference,
//                                 V newReference,
//                                 int expectedStamp,
//                                 int newStamp) {
//        Pair<V> current = pair;
//        return
//           expectedReference == current.reference && // 如果返回true则说明期待的原始对象与Pair的reference对象一样
//           expectedStamp == current.stamp &&  // 如果返回true说明期待原始对象标志版本与Pair的stamp对象一样
//           ((newReference == current.reference &&
//           newStamp == current.stamp) || // 如果期待更新的对象和标志版本与Pair的reference和stamp一样的话直接返回true，否则执行CAS操作
//           casPair(current, Pair.of(newReference, newStamp)));
//    }
//
//    public void set(V newReference, int newStamp) {
//        Pair<V> current = pair;
//        if (newReference != current.reference || newStamp != current.stamp)
//            this.pair = Pair.of(newReference, newStamp);
//    }
//
//    public boolean attemptStamp(V expectedReference, int newStamp) {
//        Pair<V> current = pair;
//        return
//                expectedReference == current.reference &&
//                        (newStamp == current.stamp ||
//                                casPair(current, Pair.of(expectedReference, newStamp)));
//    }
//
//    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
//    private static final long pairOffset =
//            objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);
//
//    private boolean casPair(Pair<V> cmp, Pair<V> val) {
//        return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
//    }
//
//    static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
//                                  String field, Class<?> klazz) {
//        try {
//            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
//        } catch (NoSuchFieldException e) {
//            NoSuchFieldError error = new NoSuchFieldError(field);
//            error.initCause(e);
//            throw error;
//        }
//    }
//}

import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.TimeUnit;

public class 使用Atomic {

	// 定义AtomicStampedReference引用操作"abc"字符串，指定初始版本号为0
	private static AtomicStampedReference<String> stampedReference = new AtomicStampedReference<>("abc", 0);

	public static void main(String[] args) {
		Thread t1 = new Thread(() -> {
			stampedReference.compareAndSet("abc","def",stampedReference.getStamp(),stampedReference.getStamp()+1);

			System.out.println(Thread.currentThread().getName() + "----" + stampedReference.getReference());

			stampedReference.compareAndSet("def","abc",stampedReference.getStamp(),stampedReference.getStamp()+1);
		});
		Thread t2 = new Thread(() -> {
			// 如果在此处获取stamp，则可能无法获取当前的版本号，在线程睡眠的那一秒中，版本号可能发生了改变
			// int stamp=stampedReference.getStamp();//获取版本号
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			int stamp = stampedReference.getStamp();// 获取版本号
			System.out.println(stampedReference.compareAndSet("abc", "ggg", stamp, stamp + 1));//true
		});
		t1.start();
		t2.start();
		try {
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(stampedReference.getReference());
	}
}
//(3)AtomicMarkableReference
//AtomicMarkableReference原子类与AtomicStampedReference原子类源码实现相似，区别在于AtomicMarkableReference的标记是Boolean类型，
//只有两种状态true和false，适用在只需要知道AtomicMarkableReference对象是否有被修改的情景。

//AtomicMarkableReference核心码源：
// Pair对象维护对象的引用和对象标记
/*private static class Pair<T> {
    final T reference;
    final boolean mark;// 通过标记的状态区分对象是否有更改

    private Pair(T reference, boolean mark) {
        this.reference = reference;
        this.mark = mark;
    }

    static <T> Pair<T> of(T reference, boolean mark) {
        return new Pair<T>(reference, mark);
    }
}*/
/**
 * @param expectedReference 期待的原始对象
 * @param newReference      将要更新的对象
 * @param expectedMark      期待原始对象的标记
 * @param newMark           将要更新对象的标记
 */
//public boolean compareAndSet(V expectedReference,
//                             V newReference,
//                             boolean expectedMark,
//                             boolean newMark) {
//    Pair<V> current = pair;
//    return
//        expectedReference == current.reference && // 如果期待的原始对象与Pair的reference一样则返回true
//        expectedMark == current.mark && // 如果期待的原始对象的标记与Pair的mark一样则返回true
//        ((newReference == current.reference &&
//        newMark == current.mark) || // 如果要更新的对象和对象标记与Pair的refernce和mark一样的话直接返回true，否则执行CAS操作
//        casPair(current, Pair.of(newReference, newMark)));
//}
//
//示例：
/*import java.util.concurrent.atomic.AtomicMarkableReference;
public class 使用Atomic {
    private static final Integer INIT_NUM = 10;
    private static final Integer TEM_NUM = 20;
    private static final Integer UPDATE_NUM = 100;
    private static final Boolean INITIAL_MARK = Boolean.FALSE;
    private static AtomicMarkableReference<Integer> atomicMarkableReference = new AtomicMarkableReference<>(INIT_NUM, INITIAL_MARK);
    public static void main(String[] args) {
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " ： 初始值为：" + INIT_NUM + " , 标记为： " + INITIAL_MARK);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (atomicMarkableReference.compareAndSet(INIT_NUM, UPDATE_NUM, atomicMarkableReference.isMarked(), Boolean.TRUE)) {
                System.out.println(Thread.currentThread().getName() + " ： 修改后的值为：" + atomicMarkableReference.getReference() + " , 标记为： " + atomicMarkableReference.isMarked());
            }else{
                System.out.println(Thread.currentThread().getName() +  " CAS返回false");
            }
        }, "线程A").start();

        new Thread(() -> {
            Thread.yield();
            System.out.println(Thread.currentThread().getName() + " ： 初始值为：" + atomicMarkableReference.getReference() + " , 标记为： " + INITIAL_MARK);
            atomicMarkableReference.compareAndSet(atomicMarkableReference.getReference(), TEM_NUM, atomicMarkableReference.isMarked(), Boolean.TRUE);
            System.out.println(Thread.currentThread().getName() + " ： 修改后的值为：" + atomicMarkableReference.getReference() + " , 标记为： " + atomicMarkableReference.isMarked());
        }, "线程B").start();
    }
}*/

//输出结果：
//
//线程A ： 初始值为：10 , 标记为： false
//线程B ： 初始值为：10 , 标记为： false
//线程B ： 修改后的值为：20 , 标记为： true
//线程A CAS返回false
//
//由于线程B修改了对象，标记有false改为true，所以当上下文切换为线程A的时候，如果标记不一致CAS方法就会返回false
